package gnssio

import (
	"dgo/goutils/dnet"
	"dgo/goutils/gis"
	"dgo/goutils/utils"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
)

/*
 * NtripSvr方式推送数据
 */
type CommNtripSvrV2 struct {
	flag       byte
	twKey      int32
	postHeader []byte
	client     *dnet.ASyncTcpClient
	listeners  *utils.SafeList
	user       string
	pass       string
	authstr    string
	nmea       *gis.NMEA
	mountpoint string
	TimeOutSec int
}

func NewCommNtripSvrV2(addr string, mountpoint string, user, pass string) *CommNtripSvrV2 {

	rval := &CommNtripSvrV2{
		flag:       0,
		mountpoint: mountpoint,
		user:       user,
		pass:       pass,
		client:     dnet.NewASyncTcpClient(),
		listeners:  utils.NewSafeList(),
		TimeOutSec: 30,
	}

	str := rval.user + ":" + rval.pass
	rval.authstr = base64.StdEncoding.EncodeToString([]byte(str))

	rval.client.UseQueueSend = false
	rval.client.SetAddress(addr)
	rval.client.OnRecvBuffer = rval.onRecvClientBuffer
	rval.client.OnConnected = rval.onConnected
	rval.client.OnDisconnected = rval.onDisconnected
	return rval
}

/*
*

	ntrip2svr://USER:PASS@IP:PORT/MOUNTPOINT
*/
func NewCommNtripSvrV2FromCmd(cmdstr string) *CommNtripSvrV2 {

	ok, cmdstr := utils.CheckTrimPrefix(cmdstr, "ntrip2svr://")
	if !ok {
		return nil
	}

	// USER:PASS@IP:PORT/MOUNTPOINT
	connString := cmdstr
	strAddr := connString
	idx := strings.LastIndex(connString, "@")
	strUser := ""
	strPass := ""
	if idx != -1 {
		strAuth := connString[:idx]
		strs := strings.SplitN(strAuth, ":", 2)
		if len(strs) == 2 {
			strUser = strs[0]
			strPass = strs[1]
		} else {
			strUser = strs[0]
		}
		strAddr = connString[idx+1:]
	}

	// IP:PORT/MOUNTPOINT
	strs := strings.SplitN(strAddr, "/", 2)
	if len(strs) != 2 {
		return nil
	}
	addr := strs[0]
	mp := strs[1]

	return NewCommNtripSvrV2(addr, mp, strUser, strPass)

}

func CreateNtrip2SvrCommFromCmdLineFunc(args ...interface{}) (rval interface{}, err error) {
	if len(args) < 1 {
		return nil, errors.New("至少要传入一个参数")
	}
	cmdStr := args[0].(string)
	if len(cmdStr) == 0 {
		return nil, errors.New("命令参数非法")
	}
	return NewCommNtripSvrV2FromCmd(cmdStr), nil
}

func (this *CommNtripSvrV2) onConnected(sender *dnet.ASyncTcpClient) {
	this.client.PostSendBuffer(this.postHeader)
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnConnect(this)
	})

}

func (this *CommNtripSvrV2) onDisconnected(sender *dnet.ASyncTcpClient) {
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnDisconnect(this)
	})
}

// =================================================================
func (this *CommNtripSvrV2) onRecvClientBuffer(client *dnet.ASyncTcpClient, buffer []byte) {
	this.listeners.ForEach(func(val interface{}) {
		val.(I_CommListener).OnReceive(this, buffer, len(buffer))
	})
}

// =================================================================
func (this *CommNtripSvrV2) Start() {

	str := "POST /" + this.mountpoint + " HTTP/1.1\r\n"
	str += "Ntrip-Version: Ntrip/2.0\r\n"
	str += fmt.Sprintf("Authorization: Basic %s\r\n", this.authstr)
	str += "User-Agent: NTRIP DNtripServer/2.0\r\n"
	str += "Transfer-Encoding: chunked\r\n"
	str += "Connection: close\r\n"
	str += "\r\n"
	this.postHeader = []byte(str)

	this.client.Start()
	this.flag = 1

}

func (this *CommNtripSvrV2) Stop() {
	this.client.Stop()
	this.flag = 0
}

func (this *CommNtripSvrV2) Send(buf []byte, len int) int {
	return this.client.PostSendBuffer(buf[:len])
}

func (this *CommNtripSvrV2) AddListener(event I_CommListener) {
	if this.listeners.Exists(event) {
		utils.Log.Warn("I_CommListener已经存在请勿重复侦听")
		return
	}
	this.listeners.Add(event)
}

func (this *CommNtripSvrV2) RemoveListener(event I_CommListener) {
	this.listeners.Remove(event)
}
